package com.objects.demo02;

public class Test {
    public static void main(String[] args) {
        // 判断两个基本数据类型的数据是否相等直接使用 "=="
        int a = 100;
        int b = 100;
        double c = 100; // 不同数据类型
        System.out.println(a == b); // true
        System.out.println(a == c); // true
        // 判断两个对象是否相等，可以使用 "==" 吗？ 不可以的 因为 ==  判断对象的内存地址是否相等
        MyTime t1 = new MyTime(2021, 12, 16);
        MyTime t2 = new MyTime(2021, 12, 16);
        // 这里的 "==" 判断的是t1 中保存的对象内存地址和t2中保存的对象内存地址是否相等
        System.out.println(t1 == t2); // false
        /**
         * == 是运算符
         * 关于 ==  总结：
         * 当 == 两边属于基本类型：判断基本数据的数值是否相等，相等：true ，否则：false
         * 当 == 两边属于引用类型：判断的是对象的在堆中的内存地址的值是否相等，相等：true 否则：false
         */
        System.out.println("===equals学习===");
        /**
         * equals 是Object类的方法
         * equals 用于判断两个对象是否相等的方法，返回值为布尔类型
         * Object 的 equals方法源码：
         *     obj 表示传入的对象
         *     public boolean equals(Object obj) {
         *         return (this == obj);  默认使用 == 判断，即是对象的在堆中的内存地址的值是否相等
         *     }
         * 所有为了满足自身程序需要，我们必须对于 Object的equals 方法进行重写。如果没有重写 equals方法
         * 那么引用类型的 equals 方法 默认是 == 比较内存地址。
         */
        // 比较两个对象是否相等
        System.out.println(t1.equals(t2));  // false 比较对象的在堆中的内存地址
        MyTime t3 = t1;                     // 同一个引用指向，上面 t1 =  new MyTime 创建了对象，把对象的内存地址赋值给t1,这里相当于把t1的对象地址值重新赋值给 t3
        System.out.println(t1.equals(t3));  // true  内存地址一样

        /**
         * 重写equals（根据自己要求）
         * 如果内容一样（年月日），我们认为这两个对象是相等的。
         * 1、判断传入的对象是否为 null，是：false
         * 2、判断传入的对象是否为 该类的实例
         * 3、判断年月日的值是否相等
         * @Override
         *     public boolean equals(Object obj) {
         *         if (obj == null || !(obj instanceof Object)) {
         *             return false;
         *         }
         *         if (this  == obj) {
         *             return true;
         *         }
         *         // 类型转换
         *         MyTime t = (MyTime) obj;
         *         return this.year == t.year && this.month ==  t.month && this.day ==t.day;
         *     }
         */

        System.out.println("==重写测试！==");
        System.out.println(t1.equals(t2));  // true

        /**
         * String类中的 equals方法。（String类根据自己要求重写了）
         * 源码：
         *     public boolean equals(Object anObject) {
         *         if (this == anObject) { 判断内存地址
         *             return true;
         *         }
         *         if (anObject instanceof String) {
         *             String aString = (String)anObject;
         *             判断编码方式是否相同
         *             if (coder() == aString.coder()) {
         *                 return isLatin1() ? StringLatin1.equals(value, aString.value)
         *                                   : StringUTF16.equals(value, aString.value);
         *             }
         *         }
         *         编码方式不同直接返回 false
         *         return false;
         *     }
         * 源码可以看得出来 String类中的 equals方法 不仅判断对象的内存地址相等，还判断内容是否相等
         */
        System.out.println("==分析String类的equals方法==");
        /**
         * 1、String作为一个对象来使用
         * 例子一：对象不同，内容相同，"==" 返回false，equals返回true
         */
        String s1 = new String("java");
        String s2 = new String("java");
        System.out.println(s1 == s2); // false 对象内存地址不一样
        System.out.println(s1.equals(s2)); // true

        /**
         * 例子二：对象相同，"==" 返回 true，equals返回true
         */
        System.out.println("===例子二===");
        String n1 = new String("ymb");
        String n2 = n1;
        String n3 = "ymb";
        System.out.println(n1 == n2); // true
        System.out.println(n1.equals(n2)); // false
        System.out.println("---------");
        System.out.println(n1.equals(n3)); // true

        /**
         * 例子三：如果值不相同，对象就不相同，所以"==" 和equals结果一样 false
         * 值相同，对象相同
         */
        System.out.println("===例子三===");
        String  m1 = "java study";
        String  m2 = "java study";
        String  m3 = "php study";
        String  m4 = new String("php study");
        System.out.println(m1 == m2);       // true
        System.out.println(m1.equals(m2));  // true
        System.out.println(m3.equals(m2));  // false
        System.out.println(m3.equals(m4));  // true
        System.out.println(m3 == m4);       // false


        System.out.println("====Integer 类的 equals方法===");
        /**
         * Integer 类的 equals方法
         *     public boolean equals(Object obj) {
         *         if (obj instanceof Integer) {
         *             return value == ((Integer)obj).intValue();
         *         }
         *         return false;
         *     }
         * equals 判单数值是否相等
         */
        Integer f = new Integer(100);
        Integer e = new Integer(100);
        Integer k = 100;
        System.out.println(f ==  e);        // false 对象的内存地址 不一样
        System.out.println(f.equals(e));    // true
        System.out.println(f.equals(k));    // true
    }
}
